package guiTest;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.security.AllPermission;
import java.util.ArrayList;
import java.util.Map;
import java.util.Random;

import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioSystem;

public class SongData
{
	Random randomGenerator;
	ArrayList<Song> allSongs;
	int totalOfAllSongRatings;
	public final static int MAX_WEIGHT = 100;
	
	public final static String MAIN_DIR = "C:\\Documents and Settings\\" + 
		"BJ\\My Documents\\My Files\\HTML_Stuff\\music"; 
	
	public final static String SEPARATOR = ":=:";
	public final static String SEPARATOR2 = " " + SEPARATOR + " ";
	
	public SongData()
	{
		randomGenerator = new Random();
		allSongs = new ArrayList<Song>();
		
		populateSongData();
	}
	
	public void populateSongData()
	{
		try
		{	
			//String PARENT_DIR = "C:\\Documents and Settings\\BJ\\My Documents\\My Files" + 
			//"\\HTML_Stuff"; 
			
			ArrayList<String> orderedArtistNames = new ArrayList<String>();
			File orderedArtists = new File(MAIN_DIR + "\\artistNames.txt");
			FileReader orderedArtistsFileReader = new FileReader(orderedArtists);
			BufferedReader orderedArtistsBufferedReader = 
				new BufferedReader(orderedArtistsFileReader);
			
			String artistFolderName = orderedArtistsBufferedReader.readLine();
			
			while(artistFolderName != null)
			{
				orderedArtistNames.add(artistFolderName);
				artistFolderName = orderedArtistsBufferedReader.readLine();
			}
			
			orderedArtistsBufferedReader.close();
			orderedArtistsFileReader.close();
				
			//File rootFolder = new File(MAIN_DIR);
			//String artistFolderNames[] = rootFolder.list();
			int sumOfPreviousRatings = 0;
			int songID = 0;
			
			for(String artistFoldername : orderedArtistNames)
			{	
				boolean writeBack = false;
				ArrayList<String> fileLines = new ArrayList<String>();
				String artistFolderPath = MAIN_DIR + "\\" + artistFoldername;
				File artistTrackNamesFile = new File(artistFolderPath + "\\trackNames.txt");
				
				FileReader fr = new FileReader(artistTrackNamesFile);
				BufferedReader br = new BufferedReader(fr);
				
				String artistName = br.readLine().trim();
				//System.out.println("Loading artist: " + artistName);
				fileLines.add(artistName);
	
				//Skip an empty line
				String lineRead = br.readLine();
				fileLines.add("");
								
				lineRead = br.readLine();
				
							
				while(lineRead != null)
				{
					//System.out.println(lineRead);
					String songComponents[] = lineRead.split(SEPARATOR);
					Song nextSong = new Song();
					
					nextSong.setArtist(artistName);
					nextSong.setBandFolderName(artistFoldername);
					nextSong.setFilename(songComponents[0].trim());
					nextSong.setSong(songComponents[3].trim());
					
					Integer myInt = new Integer(songComponents[1].trim());
					nextSong.setRating(myInt.intValue());
					nextSong.setSumOfPreviousRatings(sumOfPreviousRatings);
					nextSong.setSongNumber(songID);
					
					String durationString = songComponents[2].trim();
					if(durationString.equalsIgnoreCase("not_set"))
					{
						durationString = "0";
					}					
					
					Integer durationInt = new Integer(durationString);
					
					if(durationInt < 10)
					{
						writeBack = true;
						File songFile = new File(MAIN_DIR + "\\" + artistFoldername +
								"\\" + nextSong.getFilename());
						AudioFileFormat baseFileFormat =
						    AudioSystem.getAudioFileFormat(songFile);
						Map<String, Object> properties = baseFileFormat.properties();
						Long songDuration = (Long)(properties.get("duration"));
						
						durationString = "" + (songDuration / 1000);
						durationInt = new Integer(durationString);
					}
					
					nextSong.setDuration(durationInt.intValue());
					
					String reformattedLine = getSpacedString(nextSong.getFilename(), 12) + 
						SEPARATOR2 + getSpacedString("" + nextSong.getRating(), 3) + SEPARATOR2 + 
						getSpacedString("" + nextSong.getDuration().getDurationVal(), 7) + 
						SEPARATOR2 + nextSong.getSong();
					fileLines.add(reformattedLine);
					
					allSongs.add(nextSong);
					sumOfPreviousRatings += myInt.intValue();
					songID++;
					
				
					
					lineRead = br.readLine();
				}
				
				if(writeBack)
				{
					FileWriter fw3 = new FileWriter(artistTrackNamesFile);
					BufferedWriter bw3 = new BufferedWriter(fw3);
					
					for(String h : fileLines)
					{
						bw3.write(h + "\n");
					}
					
					bw3.close();
					fw3.close();
				}
				
				br.close();
				fr.close();
			}
			
			totalOfAllSongRatings = sumOfPreviousRatings;
			
			File f5 = new File(MAIN_DIR + "\\AllSongs.txt");
			FileWriter fw5 = new FileWriter(f5);
			BufferedWriter bw5 = new BufferedWriter(fw5);
			
			for(int w = 0; w < allSongs.size(); w++)
			{
				Song curr = allSongs.get(w);
				bw5.write(getSpacedString(curr.getDuration().toString(), 10) +
						  getSpacedString(curr.getArtist(), 47) + 
						  curr.getSong() + "\n");
			}
			
			bw5.close();
			fw5.close();
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
	
	public Song getRandomSong()
	{
		int totalTickets = totalOfAllSongRatings;
		
		int k = randomGenerator.nextInt(totalTickets);
			
		int minObjIndex = 0;
		int maxObjIndex = allSongs.size() - 1;
		boolean found = false;
		int foundIndex = 0;
		
		while(!found)
		{
			int toSearch = (minObjIndex + maxObjIndex) / 2;
			Song w = allSongs.get(toSearch); 
			
			if(w.getRating() + w.getSumOfPreviousRatings() <= k)
			{
				// Search up
				minObjIndex = toSearch + 1;
			}
			else if(w.getSumOfPreviousRatings() > k)
			{
				// Search down
				maxObjIndex = toSearch - 1;
			}
			else
			{
				// Just right
				found = true;
				foundIndex = toSearch;
			}
				
		}
		
		return allSongs.get(foundIndex);
	}
	
	public int getNumberOfSongs()
	{
		return allSongs.size();
	}
	
	public Song getSong(int rowIndex)
	{
		return allSongs.get(rowIndex);
	}
	
	public void updateSongRating(Integer newRating, int row)
	{
		Song songToUpdate = allSongs.get(row);
		Integer oldRating = songToUpdate.getRating();
		
		int difference = newRating.intValue() - oldRating.intValue();
		if(difference != 0)
		{
			songToUpdate.setRating(newRating.intValue());
			for(int g = row + 1; g < allSongs.size(); g++)
			{
				Song current = allSongs.get(g); 
				int currentSum = current.getSumOfPreviousRatings().intValue();
				current.setSumOfPreviousRatings(currentSum + difference);
			}
			
			// Update the file
			String artistFolder = songToUpdate.getBandFolderName();
			File f = new File(MAIN_DIR + "\\" + artistFolder + "\\trackNames.txt");
			ArrayList<String> lines = new ArrayList<String>();
			String songKey = songToUpdate.getFilename(); 
			try
			{
				FileReader fr = new FileReader(f);
				BufferedReader br = new BufferedReader(fr);
				String lineRead = br.readLine();
				
				while(lineRead != null)
				{
					if(lineRead.contains(songKey))
					{
						String h[] = lineRead.split(SEPARATOR);
						h[1] = "" + newRating;
						
						String newLineRead = getSpacedString(h[0].trim(), 12) + 
						SEPARATOR2 + getSpacedString("" + h[1].trim(), 3) + SEPARATOR2 + 
						getSpacedString("" + h[2].trim(), 7) + SEPARATOR2 + 
						h[3].trim();
						lines.add(newLineRead);
					}
					else
					{
						lines.add(lineRead);
					}
					lineRead = br.readLine();
				}
				
				br.close();
				fr.close();
				
				FileWriter fw = new FileWriter(f);
				BufferedWriter bw = new BufferedWriter(fw);
				
				for(String k : lines)
				{
					bw.write(k + "\n");
				}
				
				bw.close();
				fw.close();
			}
			catch(Exception e)
			{
				e.printStackTrace();				
			}
		}			
	}
	
	public static String getSpacedString(String toPrint, int width)
	{
		String toReturn = toPrint;
		
		if(toReturn.length() > width)
		{
			toReturn = toReturn.substring(0, width);
		}
		else
		{
			while(toReturn.length() < width)
			{
				toReturn += " ";
			}
		}
		
		return toReturn;
	}
}
